/// <reference path="tUnit.ts" />
/// <reference path="app.ts" />

class Int32 {
    /** 0x7FFFFFFF **/
    static  MAX_VALUE =0x7FFFFFFF;
}


module TriangleTests {
    /** Test functions of tUnit **/
    export class tUnitTests extends tUnit.TestClass {
        TestTrue() {
            Assert.isTrue(true);
        }

        TestFalse() {
            Assert.isFalse(false);
        }

        TestStringEqual() {
            Assert.equal("abc", "ab" + "c");
        }

        TestThrows() {
            Assert.throws(
                () => { throw "Hey"; }
                );
        }
        
        TestThrowsButNoException() {
            Assert.throws(
                () => { }
                );
        }

        TestEqualFloatingNumber() {
            Assert.equalNumber(0.1 + 0.2, 0.3);
            Assert.equalNumber((0.1 + 0.2) / 123.3457 * 123.4477, 0.3 / 123.3457 * 123.4477);
        }
        
        TestNotEqualFloatingNumber() {
            Assert.notEqualNumber((0.1 + 0.2) / 123.3457 * 123.4477, 0.3000000001 / 123.3457 * 123.4477);
        }
    
    }

    //SetUp and tearDown should perform for each test.
    export class tUnitTestsForSetUp extends tUnit.TestClass {
        private i: number = 1;
        setUp() {
            this.i++;
        }

        tearDown() {
            this.i--;
        }

        TestI() {
            Assert.equal(this.i, 2);
        }

        TestI2() {
            Assert.equal(this.i, 2);
        }

    }

    export class tUnitTestsForSetUpWithExceptionOnce extends tUnit.TestClass {
        private i: number = 1;
        setUp() {
            this.i++;
            if (this.i === 2) {
                throw "This is expected. And the setUp exception will be thrown only once. 1 instance expected.";
            }
        }

        tearDown() {
            this.i--;
        }

        TestI() {
            Assert.isTrue(this.i > 2);
        }

        TestI2() {
            Assert.isTrue(this.i > 2);
        }

    }

    export class tUnitTestsForSetUpWithException extends tUnit.TestClass {
        setUp() {
            throw "This is expected inside setUp for tUnitTestsForSetUpWithException, so no test in this class will perform. You must not fix this. 2 instances expected";
        }

        tearDown() {
            Assert.fail();
        }

        TestI() {
            Assert.fail();
        }

        TestI2() {
            Assert.fail();
        }

    }

    export class tUnitTestsForTestFixtureSetUpWithException extends tUnit.TestClass {

        testFixtureSetUp() {
            throw "This is expected inside setUp for tUnitTestsForSetUpWithException, so no test in this class will perform. You must not fix this. 1 instance expected.";
        }

        testFixtureTearDown() {
            Assert.fail();
        }

        TestI() {
            Assert.fail();
        }

        TestI2() {
            Assert.fail();
        }

    }

    //testFixtureSetUp and testFixturetearDown should perform once for TestFixture.
    export class tUnitTestsForTestFixtureSetUp extends tUnit.TestClass {
        private i: number = 1;
        testFixtureSetUp() {
            this.i++;
        }

        testFixtureTearDown() {
            this.i--;
        }

        TestI() {
            Assert.equal(this.i, 2);
        }

        TestI2() {
            Assert.equal(this.i, 2);
        }

    }




    export class SimpleTests extends tUnit.TestClass {
        ShouldBeEqual() {
            var r = GetTriangleType(100, 100, 100);
            Assert.equal(TriangleType.Equilateral, r);
        }
        
        shouldBeEquilateral() {
            Assert.equal(TriangleType.Equilateral, GetTriangleType(100, 100, 100));
        }

        shouldBeIsosceles() {
            Assert.equal(TriangleType.Isosceles, GetTriangleType(100, 100, 90));
        }

        shouldBeScalene() {
            Assert.equal(TriangleType.Scalene, GetTriangleType(100, 33, 90));
        }

        zeroSideShouldBeError() {
            Assert.equal(TriangleType.Error, GetTriangleType(0, 33, 90));
        }

        negativeSideShouldBeError() {
            Assert.equal(TriangleType.Error, GetTriangleType(-3, 33, 90));
            Assert.equal(TriangleType.Error, GetTriangleType(3, -33, 90));
        }

        malformedSidesShouldBeError() {
            Assert.equal(TriangleType.Error, GetTriangleType(100, 100, 200));

        }
       
        
        shouldBeIsoscelesWithMaxValue() {
            Assert.equal(TriangleType.Isosceles, GetTriangleType(Int32.MAX_VALUE - 1000, Int32.MAX_VALUE - 1000, Int32.MAX_VALUE));
            Assert.equal(TriangleType.Isosceles, GetTriangleType(Int32.MAX_VALUE, Int32.MAX_VALUE, 1));
        }

                    


    }

    class TestContextHelper {
        static equalNumber(expected: number, actual: number): bool {
            if (Math.abs(expected - actual) >= 0.0000000000000001) {
                throw 'equal failed when passed ' + '{' + (typeof expected) + '} "' + expected + '" and ' + '{' + (typeof actual) + '} "' + actual + '"';
            }

            return true;
        }
    }

}


window.onload = function () {
    var test = new tUnit.Test();
    
    test.addTestClass(new TriangleTests.SimpleTests(), 'SimpleTests');
    test.addTestClass(new TriangleTests.tUnitTests(), 'tUnitTests');
    test.addTestClass(new TriangleTests.tUnitTestsForSetUp(), 'tUnitTestsForSetUp');
    test.addTestClass(new TriangleTests.tUnitTestsForSetUpWithException(), 'tUnitTestsForSetUpWithException');
    test.addTestClass(new TriangleTests.tUnitTestsForSetUpWithExceptionOnce(), 'tUnitTestsForSetUpWithExceptionOnce');
    test.addTestClass(new TriangleTests.tUnitTestsForTestFixtureSetUp(), 'tUnitTestsForTestFixtureSetUp');
    test.addTestClass(new TriangleTests.tUnitTestsForTestFixtureSetUpWithException(), 'tUnitTestsForTestFixtureSetUpWithException');
    test.showResults(document.getElementById('results'), test.run());


};
